/**
 * defineProperty 做数据劫持 -> 给对象进行扩展 -> 属性进行设置
 * 1、defineProperty:
var obj = {}
defineProperty(obj,'属性名',{
})

**注：**实际上是直接处理obj对象
2、Proxy:
var proxy = new Proxy(obj)
 */

var target = {
  a: 1,
  b: 2,
};

var proxy = new Proxy(target, {
  get(target, prop) {
    //target 是target 对象   prop 是 target对象里面的属性
    console.log("This is property value " + target[prop]);
    //必须要返回一个值
  },
  set(target, prop, value) {
    target[prop] = value; //所以有第三个参数value，将对应的值传给需要修改的属性
    console.log(target[prop]);
  },
});

// proxy.a;

// proxy.b = 3; //log -> 2
// console.log(proxy.b);
//因为set里面没有处理

//Proxy 能不能处理函数呢？

let fn = function () {
  console.log("I am a function.");
};

fn.a = 123;

let newFn = new Proxy(fn, {
  get(fn, prop) {
    return fn[prop] + " This is a Proxy return";
  },
});

// console.log(newFn.a); //123This is a Proxy return
var obj = {
  a: 112,
};
var extensible = Object.isExtensible(obj);
// console.log(extensible); //true
// 看obj能不能追加、删除、可枚举、可配置等

// Object.freeze(obj); //冻结obj

var extensible2 = Object.isExtensible(obj);
// console.log(extensible2); //false

//从JavaScript引擎底层抛出来的这些API实际上都是函数式的

// Object.seal(obj); //封闭对象
obj.c = 3; //不可修改
// console.log(obj); //{a:1,b:2}

delete obj.a; //不可删除
// console.log(obj); //{a:1,b:2}

obj.a = 34; //可写的
// console.log(obj); //{a:1,b:3}

for (var key in obj) {
  //   console.log(obj[key]); //1  3  可读
}

//////////==================获取自由属性[[GetOwnProperty]]
Object.setPrototypeOf(obj, { c: 3, d: 4 });
console.log(Object.getOwnPropertyNames(obj)); //["a","b"]
console.log(obj.hasOwnProperty("d")); //检查有没有a属性

//////////==================禁止扩展对象[[PreventExtensions]]
// Object.preventExtensions(obj);
// obj.c = 3;//禁止增加属性
// console.log(obj);//{a:1,b:2}
// delete obj.a;
// console.log(obj);//{b:2} 可以删除属性

//////////==================proxy对象

let target2 = {
  a: 1,
  b: 2,
};
console.log("=================");
let proxy2 = new Proxy(target2, {
  get(target, prop) {
    return "GET" + prop + " = " + target2[prop];
  },
  set(target, prop, value) {
    target2[prop] = value;
    console.log("SET:" + prop + " = " + value);
  },
  has(target, prop) {
    console.log(target2[prop]); //1
  },
  deleteProperty(target, prop) {
    delete target2[prop];
  },
});

console.log("a" in proxy2); //false
//a 属于proxy下面的Target
delete proxy2.b;
console.log(proxy2); //Proxy  {a:1}

// Proxy 所有的内部方法转发给target,handler写的方法是对内部方法的重写,外界通过Proxy去访问target属性时，会经过handler中的每一个方法。
//可以通过重写handler中的一些方法来进行拦截，实际上并不是拦截，是通过代理的方式，先去操作proxy,然后痛proxy代理内部的这些方法去更改或操作target对象
